package com.cosmoplat.xikai.business.service.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.Duration;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cosmoplat.xikai.business.domain.*;
import com.cosmoplat.xikai.business.domain.dto.scada.DeviceFaultDto;
import com.cosmoplat.xikai.business.domain.vo.DeviceStatusVo;
import com.cosmoplat.xikai.business.domain.vo.TaskForCreateProductVo;
import com.cosmoplat.xikai.business.enums.*;
import com.cosmoplat.xikai.business.modbus.utils.Modbus4jUtils;
import com.cosmoplat.xikai.business.scada.ScadaData;
import com.cosmoplat.xikai.business.service.*;
import com.cosmoplat.xikai.common.core.domain.AjaxResult;
import com.cosmoplat.xikai.common.core.redis.RedisCache;
import com.cosmoplat.xikai.common.enums.business.MesTaskStatusEnum;
import com.cosmoplat.xikai.common.enums.business.TaskPlanStatusEnum;
import com.cosmoplat.xikai.common.exception.ServiceException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import static com.cosmoplat.xikai.common.utils.Threads.sleep;


/**
 * 设备调用服务实现类
 */
@Service
@Slf4j
public class DeviceCallServiceImpl implements DeviceCallService {
    @Autowired
    private DeviceLogService deviceLogService;
    @Autowired
    private DeviceUsageRecordService deviceUsageRecordService;
    @Autowired
    private BaseProductInfoService baseProductInfoService;
    @Autowired
    private DeviceProductLogService deviceProductLogService;
    @Autowired
    private BaseDispatchTaskService baseDispatchTaskService;
    @Autowired
    private BaseAlarmRecordService baseAlarmRecordService;
    @Autowired
    private BaseDeliveryInfoService deliveryInfoService;
    @Autowired
    private BackService backService;
    @Autowired
    private BaseMesNotUploadService baseMesNotUploadService;
    @Autowired
    private ScadaData scadaData;

    /**
     * 扭矩最小值
     */
    @Value("${torque.min}")
    private String min;
    /**
     * 扭矩最大值
     */
    @Value("${torque.max}")
    private String max;
    /**
     * 报警缓存map
     */
    private static final HashMap<Long, DeviceLog> WARN_DEVICE_MAP = new HashMap<>();
    /**
     * 产品缓存map
     */
//    private static final HashMap<String, BaseProductInfo> PRODUCT_MAP = new HashMap<>();
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private DeviceThingModelService deviceThingModelService;


    @Override
    public void saveData(String deviceCodes) {
        if (deviceCodes != null) {
            String[] deviceCodeList = deviceCodes.split(",");
            //设备编号
            for (String deviceCode : deviceCodeList) {
                //获取设备运行状态
                DeviceLog runStatusLog = scadaData.getDeviceLog(DeviceParamsEnum.RUN_STATE.getName());
                DeviceThingModel deviceThingModel = scadaData.getDeviceThingModel(deviceCode, DeviceParamsEnum.RUN_STATE.getName(), 1);
                //判断设备状态
                if (runStatusLog == null) {
                    //如果返为null默认表示设备并为连接上,判断为离线——>并保存到device_log表中
//                    DeviceLog deviceLog = new DeviceLog(deviceThingModel.getDeivceId(), deviceThingModel.getId(), DeviceRunStatusEnum.OFFLINE.getCode(), 1, new Date(), DeviceRunStatusEnum.OFFLINE.getCode(), new Date());
                    DeviceLog deviceLog = new DeviceLog(deviceThingModel.getDeviceId(), deviceThingModel.getId(), DeviceRunStatusEnum.OFFLINE.getCode(), 1, new Date(), DeviceRunStatusEnum.OFFLINE.getCode(), new Date());
                    //保存设备数据
                    deviceLogService.save(deviceLog);
                    continue;
                } else {
                    //保存设备数据
                    deviceLogService.save(runStatusLog);
                }
                String runStatus = runStatusLog.getVal();
                //获取能耗
                DeviceLog energyConsumptionDeviceLog = scadaData.getDeviceLog(DeviceParamsEnum.ENERGY_CONSUMPTION.getName());

                DeviceThingModel energyConsumptionDeviceThingModel = scadaData.getDeviceThingModel(deviceCode, DeviceParamsEnum.ENERGY_CONSUMPTION.getName(), 1);
                if (energyConsumptionDeviceLog != null) {
                    //保存设备数据
                    energyConsumptionDeviceLog.setVal(new BigDecimal(energyConsumptionDeviceLog.getVal()).divide(new BigDecimal(100),2,BigDecimal.ROUND_HALF_UP).toString());
                    energyConsumptionDeviceLog.setDeviceStatus(runStatusLog.getVal());
//                    deviceLogService.save(energyConsumptionDeviceLog);
                }
                //获取扭矩值
                DeviceLog currentMaximumMomentDeviceLog = scadaData.getDeviceLog(DeviceParamsEnum.CURRENT_MAXIMUM_MOMENT.getName());
                if (currentMaximumMomentDeviceLog != null) {
                    currentMaximumMomentDeviceLog.setDataTime(new Date());
                    currentMaximumMomentDeviceLog.setDeviceStatus(runStatusLog.getVal());
                    //保存设备数据
                    deviceLogService.save(currentMaximumMomentDeviceLog);
                }
                //获取压力值
                DeviceLog maximumWorkingMomentDeviceLog1 = scadaData.getDeviceLog(DeviceParamsEnum.MAXIMUM_WORKING_MONMENT1.getName());
                if (maximumWorkingMomentDeviceLog1 != null) {
                    maximumWorkingMomentDeviceLog1.setDataTime(new Date());
                    maximumWorkingMomentDeviceLog1.setDeviceStatus(runStatusLog.getVal());
                    //保存设备数据
                    deviceLogService.save(maximumWorkingMomentDeviceLog1);
                }
                DeviceLog maximumWorkingMomentDeviceLog2 = scadaData.getDeviceLog(DeviceParamsEnum.MAXIMUM_WORKING_MONMENT2.getName());
                if (maximumWorkingMomentDeviceLog2 != null) {
                    maximumWorkingMomentDeviceLog2.setDataTime(new Date());
                    maximumWorkingMomentDeviceLog2.setDeviceStatus(runStatusLog.getVal());
                    //保存设备数据
                    deviceLogService.save(maximumWorkingMomentDeviceLog2);
                }
                //获取设备报警信息
                ArrayList<String> identiflerList = DeviceWarnEnum.getIdentiflerList();
                ArrayList<DeviceLog> warnLogList = new ArrayList<>();
                //循环获取当前设备报警状态
                identiflerList.forEach(identifler -> {
                    DeviceLog deviceLog = scadaData.getDeviceLog(identifler);
                    if (deviceLog != null) {
                        deviceLog.setDeviceStatus(runStatusLog.getVal());
                        warnLogList.add(deviceLog);

                    }
                });
                //循环设备报警状态并保存到数据库
                if (!warnLogList.isEmpty()) {
                    //循环判断报警
                    for (DeviceLog deviceLog : warnLogList) {
                        if (!WARN_DEVICE_MAP.containsKey(deviceLog.getDeviceThingModelId())) {
                            deviceLog.setDeviceStatus(runStatusLog.getVal());
                            //获取设备物模型id
                            Long deviceThingModelId = deviceLog.getDeviceThingModelId();
                            DeviceLog deviceLogByThingModelId = deviceLogService.getDeviceLogByThingModelId(deviceThingModelId);
                            // 设备状态记录表 - 客户要求的表结构记录
                            backService.insertEquipmentStatusBackup(deviceLog);
                            //判断最新的数据库报警状态是否是最新的报警状态
                            if (deviceLogByThingModelId != null && deviceLogByThingModelId.getVal() != null) {
                                if (!deviceLogByThingModelId.getVal().equals(deviceLog.getVal())){
                                    deviceLog.setDeviceStatus(runStatusLog.getVal());
                                    deviceLogService.save(deviceLog);
                                    WARN_DEVICE_MAP.put(deviceLog.getDeviceThingModelId(), deviceLog);
                                }

                            }else {
                                deviceLog.setDeviceStatus(runStatusLog.getVal());
                                deviceLogService.save(deviceLog);
                                WARN_DEVICE_MAP.put(deviceLog.getDeviceThingModelId(), deviceLog);
                            }

                        } else if (!WARN_DEVICE_MAP.get(deviceLog.getDeviceThingModelId()).getVal().equals(deviceLog.getVal())) {
                            deviceLog.setDeviceStatus(runStatusLog.getVal());
                            deviceLogService.save(deviceLog);
                            // 设备状态记录表 - 客户要求的表结构记录
                            backService.insertEquipmentStatusBackup(deviceLog);
                            WARN_DEVICE_MAP.put(deviceLog.getDeviceThingModelId(), deviceLog);
                        }
                    }
                }
                //设备生产记录判断
                if (runStatus.equals(DeviceRunStatusEnum.START_PRODUCTION.getCode())) {

                    if (redisCache.getCacheObject(deviceCode)==null) {
                        List<BaseProductInfo> list = baseProductInfoService.list(new LambdaQueryWrapper<BaseProductInfo>()
                                .isNull(BaseProductInfo::getEndTime)
                                .orderByDesc(BaseProductInfo::getStartTime));
                        if (list.isEmpty()) {
                            BaseProductInfo baseProductInfo = new BaseProductInfo();
                            TaskForCreateProductVo taskForCreateProduct = baseDispatchTaskService.getNowTaskForCreateProduct();
                            log.info("taskForCreateProduct:{}", taskForCreateProduct);
                            if (taskForCreateProduct!=null) {
                                baseProductInfo.setProductCode(taskForCreateProduct.getMaterialCode());
                                baseProductInfo.setProductName(taskForCreateProduct.getMaterialName());
                                DeviceLog userManagementLog = scadaData.getDeviceLog(DeviceParamsEnum.USER_MANAGEMENT.getName());
                                baseProductInfo.setOperator(userManagementLog == null ? "" : userManagementLog.getVal());
                                baseProductInfo.setProductType(taskForCreateProduct.getMaterialModel());
                                baseProductInfo.setBaseDispatchTaskId(taskForCreateProduct.getTaskId());
                                baseProductInfo.setIssuer(taskForCreateProduct.getIssuer());
                                baseProductInfo.setBaseWorkOrderId(taskForCreateProduct.getOrderId());
                                baseProductInfo.setStartTime(new Date());
                                baseProductInfoService.save(baseProductInfo);
                                list = baseProductInfoService.list(new LambdaQueryWrapper<BaseProductInfo>()
                                        .eq(BaseProductInfo::getEndTime, null)
                                        .orderByDesc(BaseProductInfo::getStartTime));
                            }

                        }
                        if (list.size() > 0) {
                            BaseProductInfo baseProductInfo = list.get(0);
                            baseProductInfo.setHandleRemark( scadaData.getDeviceLog(DeviceParamsEnum.NUMBER_OF_PARTS_CONSUMED.getName()).getVal());
                            redisCache.setCacheObject(deviceCode,baseProductInfo );
                        }

                    }
                    if (redisCache.getCacheObject(deviceCode)!=null) {
                        BaseProductInfo baseProductInfo =redisCache.getCacheObject(deviceCode);
                        if (scadaData.getDeviceLog(DeviceParamsEnum.NUMBER_OF_PARTS_CONSUMED.getName()).getVal().equals(baseProductInfo.getHandleRemark())) {
                            //获取实时的设备的扭矩
                            DeviceLog currentMaximumMoment = scadaData.getDeviceLog(DeviceParamsEnum.CURRENT_MAXIMUM_MOMENT.getName());
                            DeviceLog setMaximumTorque = scadaData.getDeviceLog(DeviceParamsEnum.SET_MAXIMUM_TORQUE.getName());
                            DeviceLog maximumWorkingMoment1 = scadaData.getDeviceLog(DeviceParamsEnum.MAXIMUM_WORKING_MONMENT1.getName());
                            DeviceLog maximumWorkingMoment2 = scadaData.getDeviceLog(DeviceParamsEnum.MAXIMUM_WORKING_MONMENT2.getName());
                            if (currentMaximumMoment != null && setMaximumTorque != null) {
                                DeviceProductLog deviceProductLog = new DeviceProductLog();
                                deviceProductLog.setProductId(baseProductInfo.getId());
                                if (energyConsumptionDeviceLog!=null) {
                                    deviceProductLog.setConsumption(new BigDecimal(energyConsumptionDeviceLog.getVal()));

                                }else {
                                    deviceProductLog.setConsumption(new BigDecimal(0));
                                }
                                deviceProductLog.setConsumptionUnit(energyConsumptionDeviceThingModel.getUnit());
                                deviceProductLog.setSpecifiedTorque(Double.parseDouble(setMaximumTorque.getVal()));
                                deviceProductLog.setMeasurTorque(Double.parseDouble(currentMaximumMoment.getVal()));
                                deviceProductLog.setCreateTime(new Date());
                                deviceProductLog.setSpecifiedTorqueMax(Double.parseDouble(max));
                                deviceProductLog.setSpecifiedTorqueMin(Double.parseDouble(min));
                                deviceProductLog.setMaximumWorkingMoment1(new BigDecimal(maximumWorkingMoment1.getVal()));
                                deviceProductLog.setMaximumWorkingMoment2(new BigDecimal(maximumWorkingMoment2.getVal()));
                                //根据扭矩进行对比判断最大值
                                Double maxDouble = Double.parseDouble(max);
                                Double minDouble = Double.parseDouble(min);
                                double val = Double.parseDouble(currentMaximumMoment.getVal());
                                if (maxDouble < val || minDouble > val) {
                                    //数据对比
                                    BaseDispatchTask doingTask = baseDispatchTaskService.getDoingTask();
                                    TaskForCreateProductVo taskForCreateProduct = baseDispatchTaskService.getNowTaskForCreateProduct();
                                    baseAlarmRecordService.qualityExceptionCallMes(doingTask, taskForCreateProduct.getMaterialCode(), "产品扭矩超过合格范围", String.valueOf(baseProductInfo.getId()));
                                }
                                deviceProductLogService.save(deviceProductLog);
                            }
                        }
                        else {
                            endOfLine(deviceCode);
                        }
                    }
//                    BaseProductInfo baseProductInfo =redisCache.getCacheObject(deviceCode);
//                    //获取实时的设备的扭矩
//                    DeviceLog currentMaximumMoment = scadaData.getDeviceLog(DeviceParamsEnum.CURRENT_MAXIMUM_MOMENT.getName());
//                    DeviceLog setMaximumTorque = scadaData.getDeviceLog(DeviceParamsEnum.SET_MAXIMUM_TORQUE.getName());
//                    DeviceLog maximumWorkingMoment1 = scadaData.getDeviceLog(DeviceParamsEnum.MAXIMUM_WORKING_MONMENT1.getName());
//                    DeviceLog maximumWorkingMoment2 = scadaData.getDeviceLog(DeviceParamsEnum.MAXIMUM_WORKING_MONMENT2.getName());
//                    if (currentMaximumMoment != null && setMaximumTorque != null) {
//                        DeviceProductLog deviceProductLog = new DeviceProductLog();
//                        deviceProductLog.setProductId(baseProductInfo.getId());
//                        deviceProductLog.setConsumption(Long.parseLong(energyConsumptionDeviceLog.getVal()));
//                        deviceProductLog.setConsumptionUnit(energyConsumptionDeviceThingModel.getUnit());
//                        deviceProductLog.setSpecifiedTorque(Double.parseDouble(setMaximumTorque.getVal()));
//                        deviceProductLog.setMeasurTorque(Double.parseDouble(currentMaximumMoment.getVal()));
//                        deviceProductLog.setCreateTime(new Date());
//                        deviceProductLog.setSpecifiedTorqueMax(Double.parseDouble(max));
//                        deviceProductLog.setSpecifiedTorqueMin(Double.parseDouble(min));
//                        deviceProductLog.setMaximumWorkingMoment1(new BigDecimal(maximumWorkingMoment1.getVal()));
//                        deviceProductLog.setMaximumWorkingMoment2(new BigDecimal(maximumWorkingMoment2.getVal()));
//                        //根据扭矩进行对比判断最大值
//                        Double maxDouble = Double.parseDouble(max);
//                        Double minDouble = Double.parseDouble(min);
//                        double val = Double.parseDouble(currentMaximumMoment.getVal());
//                        if (maxDouble < val || minDouble > val) {
//                            //数据对比
//                            BaseDispatchTask doingTask = baseDispatchTaskService.getDoingTask();
//                            TaskForCreateProductVo taskForCreateProduct = baseDispatchTaskService.getNowTaskForCreateProduct();
//                            baseAlarmRecordService.qualityExceptionCallMes(doingTask, taskForCreateProduct.getMaterialCode(), "产品扭矩超过合格范围", String.valueOf(baseProductInfo.getId()));
//                        }
//                        deviceProductLogService.save(deviceProductLog);
//                    }
                }
//                else if (runStatus.equals(DeviceRunStatusEnum.COMPLETION_STATUS_ACQUISITION.getCode())) {
//                    //判断是否处于完工状态(当设备生产完工回出现4已经像厂家确认)
//                    endOfLine(deviceCode);
//                }

            }
        }

    }

    @SuppressWarnings("checkstyle:NeedBraces")
    private void endOfLine(String deviceCode) {
        if (redisCache.getCacheObject(deviceCode)!=null) {
            //获取产品保存时的数据
            BaseProductInfo baseProductInfo = redisCache.getCacheObject(deviceCode);
            log.info(baseProductInfo+"已完工");
            //获取这段时间的产品所有的物料扭矩等数据
            List<DeviceProductLog> list = deviceProductLogService.list(new LambdaQueryWrapper<DeviceProductLog>()
                    .eq(DeviceProductLog::getProductId, baseProductInfo.getId())
                    .orderByDesc(DeviceProductLog::getCreateTime));
            Double maxDouble = Double.parseDouble(max);
            Double minDouble = Double.parseDouble(min);
            //判断所有物料是否都合格
            boolean result = false;
            for (DeviceProductLog deviceProductLog : list) {
                Double measurTorque = deviceProductLog.getMeasurTorque();
                if (measurTorque>minDouble&&measurTorque<maxDouble) {
                    result = true;
                    break;
                }
            }
            baseProductInfo.setEndTime(new Date());
            //获取开始与结束的能耗进行比较
            DeviceProductLog firstDeviceProductLog = list.get(0);
            DeviceProductLog lastDeviceProductLog = list.get(list.size() - 1);
            BigDecimal consumption = firstDeviceProductLog.getConsumption().subtract(lastDeviceProductLog.getConsumption()) ;
            //获取该产品最大压力1
            BigDecimal maximumWorkingMoment1 = list.stream().map(l -> {
                if (l.getMaximumWorkingMoment1() == null) {
                    return BigDecimal.ZERO;
                } else return l.getMaximumWorkingMoment1();
            }).max(BigDecimal::compareTo).orElse(new BigDecimal(0));
            //获取该产品最大压力2
            BigDecimal maximumWorkingMoment2 = list.stream().map(l -> {
                if (l.getMaximumWorkingMoment2() == null) {
                    return BigDecimal.ZERO;
                } else return l.getMaximumWorkingMoment2();
            }).max(BigDecimal::compareTo).orElse(new BigDecimal(0));
            baseProductInfo.setConsumption(consumption);
            baseProductInfo.setConsumptionUnit(firstDeviceProductLog.getConsumptionUnit());
            baseProductInfo.setIsQualified(result);
            baseProductInfo.setMaximumWorkingMoment1(maximumWorkingMoment1);
            baseProductInfo.setMaximumWorkingMoment2(maximumWorkingMoment2);
            baseProductInfo.setHandleRemark("");
            baseProductInfoService.updateById(baseProductInfo);
            backService.insertProcessingDataBack(baseProductInfo);
            redisCache.deleteObject(deviceCode);
            // 更新任务状态
            //todo:现场记得打开
            updateTask();
            // 检查任务是否完成
//            if (baseDispatchTaskService.getDoingTask() == null) {
//                //  当前任务已完成，停止生产
//                if (!sendCommand(deviceCode, DeviceParamsEnum.RUN_STATE.getName(), DeviceRunStatusEnum.SUSPEND_PRODUCTION.getCode())) {
//                    throw new ServiceException("下发设备暂停失败");
//                }
//            }else if (baseDispatchTaskService.getDoingTask()!=null) {
//                if (!sendCommand(deviceCode, DeviceParamsEnum.RUN_STATE.getName(), DeviceRunStatusEnum.REPRODUCTION.getCode())) {
//                    throw new ServiceException("下发重新生产失败失败");
//                }
//            }
            //todo:更改redis
//            PRODUCT_MAP.remove(deviceCode);
            ;
        }
    }

    /**
     * @date 9:52 2025/1/15
     **/
    private void updateTask() {
        BaseDispatchTask doingTask = baseDispatchTaskService.getDoingTask();
        if (doingTask == null) {
            log.info("没有进行中的任务，不进行安全库存检查");
            return;
        }
        BigDecimal completedQty = doingTask.getCompletedQty();
        if (completedQty == null) {
            completedQty = BigDecimal.ZERO;
        }
        // 任务完成数量加1
        completedQty = completedQty.add(BigDecimal.ONE);
        doingTask.setCompletedQty(completedQty);

        // 判断是否需要转序
        boolean isProductTransfer = false;
        //判断mes连接状态
        boolean mesStatus=true;
        BigDecimal productTransferNum = ProductEnum.getProductEnumByCode(doingTask.getMaterialModel());
        if (productTransferNum != null) {
            isProductTransfer = completedQty.remainder(productTransferNum).compareTo(BigDecimal.ZERO) == 0;
        } else {
            log.error("没有找到产品{}的转序数量", doingTask.getMaterialCode());
        }
        // 判断是否完成任务
        if (completedQty.compareTo(doingTask.getDispatchQty()) >= 0) {
            doingTask.setTaskStatus(MesTaskStatusEnum.FINISHED.getCode());
            doingTask.setTaskPlanStatus(TaskPlanStatusEnum.FINISHED.getCode());
            doingTask.setTaskEndTime(new Date());
            // 通知mes
            //捕获接口调用异常如果有异常则表明为接口调用失败
            try{
                baseDispatchTaskService.callMesFinishTask(doingTask);
            }catch (Exception e) {
                e.printStackTrace();
                //将未上报的数据进行保存未上报mes数据库
                BaseMesNotUpload baseMesNotUpload = baseMesNotUploadService.getOne(new LambdaQueryWrapper<BaseMesNotUpload>().eq(BaseMesNotUpload::getBaseDispatchTaskId, doingTask.getId()));
                if (baseMesNotUpload==null) {
                    baseMesNotUploadService.save(new BaseMesNotUpload(doingTask.getId(), DeviceRunStatusEnum.COMPLETION_STATUS_ACQUISITION.getCode(), new Date()));
                }else {
                    baseMesNotUpload.setBaseDispatchTaskStatus(DeviceRunStatusEnum.COMPLETION_STATUS_ACQUISITION.getCode());
                    baseMesNotUpload.setUpdateTime(new Date());
                    baseMesNotUploadService.updateById(baseMesNotUpload);
                }
                mesStatus=false;
            }

            // 完工转序
            isProductTransfer = true;
        }


        // 扣减库存 (法兰和绝缘轴的库存数)
        deliveryInfoService.deductionStockQty(doingTask);
        // 转序
        if (isProductTransfer&&mesStatus) {
            baseDispatchTaskService.productTransfer();
        }
        baseDispatchTaskService.updateById(doingTask);
    }

    public static Date convertLocalDateToDateUsingLocalDateTime(LocalDate localDate) {
        // 将 LocalDate 转换为 LocalDateTime，时间设置为当天的午夜
        java.time.LocalDateTime localDateTime = localDate.atStartOfDay();
        // 将 LocalDateTime 转换为 ZonedDateTime，使用系统默认时区
        java.time.ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.systemDefault());
        // 将 ZonedDateTime 转换为 Instant
        java.time.Instant instant = zonedDateTime.toInstant();
        // 将 Instant 转换为 Date
        return Date.from(instant);
    }


    @Override
    public boolean sendCommand(String deviceCode, String identifier, String value) {
        //下发命令
        short v = Short.parseShort(value);
        scadaData.removeSendMap(identifier);
        DeviceThingModel deviceThingModel = scadaData.getDeviceThingModel(deviceCode, identifier, 1);
        Modbus4jUtils.setRegisterValue(deviceThingModel.getSlaveId(), Integer.parseInt(deviceThingModel.getPoint()) + 200, v);
        //睡眠2秒怕返回数据还未接收到就结束了
        sleep(2000);
        // 在指令下发过程中，系统会将目标地址修改为指令数据中的指定值；当设备完成对应操作后，将自动执行地址复位操作，将该地址值清零。
        return scadaData.getSendMap(identifier) != null && scadaData.getSendMap(identifier).equals("0");
    }

    @Override
    public boolean runStatusSendCommand(String deviceCode, String typeOfTask, String numberOfTasks) {
        short runStatusV = Short.parseShort(DeviceRunStatusEnum.START_PRODUCTION.getCode());
        String productType = ProductEnum.getParam(typeOfTask);
        if (productType == null) {
            log.info("产品类型不存在"+ typeOfTask);
            throw new ServiceException("产品类型不存在"+ typeOfTask);
        }
        short typeOfTaskV = Short.parseShort(productType);
        short numberOfTasksV = Short.parseShort(numberOfTasks);
        log.info("设备发送, typeOfTask: {}, numberOfTasks: {} ", typeOfTask, numberOfTasks);
        //删除发送 map 中的 runstatus的 key
        scadaData.removeSendMap(DeviceParamsEnum.RUN_STATE.getName());
        //删除发送 map 中的 生产任务下发-种类的 key
        scadaData.removeSendMap(DeviceParamsEnum.TYPE_OF_TASK.getName());
        //删除发送 map 中的 生产任务-数量的 key
        scadaData.removeSendMap(DeviceParamsEnum.NUMBER_OF_TASKS.getName());
        //获取设备运行状态当前物模型
        DeviceThingModel runStatusDeviceThingModel = scadaData.getDeviceThingModel(deviceCode, DeviceParamsEnum.RUN_STATE.getName(), 1);
        //获取生产任务下发-种类的物模型
        DeviceThingModel typeOfTaskDeviceThingModel = scadaData.getDeviceThingModel(deviceCode, DeviceParamsEnum.TYPE_OF_TASK.getName(), 1);
        //获取生产任务-数量的物模型
        DeviceThingModel numberOfTasksDeviceThingModel = scadaData.getDeviceThingModel(deviceCode, DeviceParamsEnum.NUMBER_OF_TASKS.getName(), 1);
        log.info("设备发送, typeOfTaskDeviceThingModel: {}", numberOfTasksDeviceThingModel);
        log.info("设备发送, numberOfTasksDeviceThingModel: {} ", numberOfTasksDeviceThingModel);
        //下发修改生产状态的地址位
        Modbus4jUtils.setRegisterValue(runStatusDeviceThingModel.getSlaveId(), Integer.parseInt(runStatusDeviceThingModel.getPoint()) + 200, runStatusV);
        //下发修改生产任务下发-种类的地址位
        Modbus4jUtils.setRegisterValue(typeOfTaskDeviceThingModel.getSlaveId(), Integer.parseInt(typeOfTaskDeviceThingModel.getPoint()) + 200, typeOfTaskV);
        //下发修改生产任务-数量的地址位
        Modbus4jUtils.setRegisterValue(numberOfTasksDeviceThingModel.getSlaveId(), Integer.parseInt(numberOfTasksDeviceThingModel.getPoint()) + 200, numberOfTasksV);
        //睡眠2秒怕返回数据还未接收到就结束了
        sleep(1000);
        // 在指令下发过程中，系统会将目标地址修改为指令数据中的指定值；当设备完成对应操作后，将自动执行地址复位操作，将该地址值清零。
        log.info("RUN_STATE:{}", scadaData.getSendMap( DeviceParamsEnum.RUN_STATE.getName()));
        log.info("TYPE_OF_TASK:{}", scadaData.getSendMap( DeviceParamsEnum.TYPE_OF_TASK.getName()));
        log.info("NUMBER_OF_TASKS:{}", scadaData.getSendMap( DeviceParamsEnum.NUMBER_OF_TASKS.getName()));
        sleep(2000);
//        try {
//            return (scadaData.getSendMap( DeviceParamsEnum.RUN_STATE.getName()) != null && scadaData.getSendMap( DeviceParamsEnum.RUN_STATE.getName()).equals("0"))
//                    && (scadaData.getSendMap(DeviceParamsEnum.TYPE_OF_TASK.getName()) != null && scadaData.getSendMap(DeviceParamsEnum.TYPE_OF_TASK.getName()).equals("0"))
//                    && (scadaData.getSendMap(DeviceParamsEnum.NUMBER_OF_TASKS.getName()) != null && scadaData.getSendMap(DeviceParamsEnum.NUMBER_OF_TASKS.getName()).equals("0"));
//        }catch (Exception e){
//            e.printStackTrace();
//            throw new ServiceException("设备开工失败");
//        }
        return true;

    }

    @Override
    public String getMaterialCodeValue(String deviceCode, String materialCode) {
        //判断是相同的物料地址
        if (materialCode.equals(MaterialEnum.M_RM_100065.getCode())) {
            materialCode = MaterialEnum.M_RM_100051.getCode();
        }
        log.debug("获取物料编码的物料信息：{}", materialCode);
        DeviceThingModel deviceThingModel = scadaData.getDeviceThingModel(deviceCode, materialCode, 4);
        if (deviceThingModel == null) {
            return null;
        }
        DeviceLog deviceLog = scadaData.getDeviceLog(deviceThingModel.getIdentifier());
        if (deviceLog != null) {
            return deviceLog.getVal();
        }
        return null;
    }

    @Override
    public HashMap<String, String> getCommandReturnValueMap(String deviceCode, List<String> identifierList) {
        HashMap<String, String> map =   new HashMap<>();
        identifierList.forEach(identifier -> {
            DeviceLog runStatusLog = scadaData.getDeviceLog(identifier);
            if (runStatusLog != null) {
                map.put(identifier, runStatusLog.getVal());
            }
        });
        return map;
    }

    @Override
    public DeviceStatusVo getDeviceStatus(String deviceCode) {
        DeviceStatusVo deviceStatusVo = new DeviceStatusVo();
        deviceStatusVo.setDeviceCode(deviceCode);
        DeviceLog runStatusLog = scadaData.getDeviceLog(DeviceParamsEnum.RUN_STATE.getName());
        if (runStatusLog != null) {
            deviceStatusVo.setDeviceStatus(DeviceRunStatusEnum.getNameByCode(runStatusLog.getVal()));
        } else {
            deviceStatusVo.setDeviceStatus(DeviceRunStatusEnum.OFFLINE.getName());
        }
        return deviceStatusVo;
    }

    @Override
    public AjaxResult getTorqueAndPressure(DeviceFaultDto deviceFaultDto) {
        DeviceThingModel currentMaximumMoment = deviceThingModelService.getOne(new LambdaQueryWrapper<DeviceThingModel>().eq(DeviceThingModel::getIdentifier, DeviceParamsEnum.CURRENT_MAXIMUM_MOMENT.getName()));
        DeviceThingModel maximumWorkingMoment1 = deviceThingModelService.getOne(new LambdaQueryWrapper<DeviceThingModel>().eq(DeviceThingModel::getIdentifier, DeviceParamsEnum.MAXIMUM_WORKING_MONMENT1.getName()));
        DeviceThingModel maximumWorkingMoment2 = deviceThingModelService.getOne(new LambdaQueryWrapper<DeviceThingModel>().eq(DeviceThingModel::getIdentifier, DeviceParamsEnum.MAXIMUM_WORKING_MONMENT2.getName()));
        List<DeviceLog> currentMaximumMomentList = deviceLogService.list(new LambdaQueryWrapper<DeviceLog>()
                .ge(DeviceLog::getDataTime, deviceFaultDto.getStartTime())
                .le(DeviceLog::getDataTime, deviceFaultDto.getEndTime())
                .eq(DeviceLog::getDeviceThingModelId, currentMaximumMoment.getId()));
        List<DeviceLog> maximumWorkingMoment1List = deviceLogService.list(new LambdaQueryWrapper<DeviceLog>()
                .ge(DeviceLog::getDataTime, deviceFaultDto.getStartTime())
                .le(DeviceLog::getDataTime, deviceFaultDto.getEndTime())
                .eq(DeviceLog::getDeviceThingModelId, maximumWorkingMoment1.getId()));
        List<DeviceLog> maximumWorkingMoment2List = deviceLogService.list(new LambdaQueryWrapper<DeviceLog>()
                .ge(DeviceLog::getDataTime, deviceFaultDto.getStartTime())
                .le(DeviceLog::getDataTime, deviceFaultDto.getEndTime())
                .eq(DeviceLog::getDeviceThingModelId, maximumWorkingMoment2.getId()));
        SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
        List<String> resultTimeList = currentMaximumMomentList.stream().map(DeviceLog::getDataTime).map(dateFormat::format).collect(Collectors.toList());
        List<String> resultCurrentMaximumMomentList = currentMaximumMomentList.stream().map(DeviceLog::getVal).collect(Collectors.toList());
        List<String> resultMaximumWorkingMoment1List = maximumWorkingMoment1List.stream().map(DeviceLog::getVal).collect(Collectors.toList());
        List<String> resultMaximumWorkingMoment2List = maximumWorkingMoment2List.stream().map(DeviceLog::getVal).collect(Collectors.toList());
        HashMap<String, List<String>> map = new HashMap<>();
        map.put("time",resultTimeList);
        map.put(DeviceParamsEnum.CURRENT_MAXIMUM_MOMENT.getName(),resultCurrentMaximumMomentList);
        map.put(DeviceParamsEnum.MAXIMUM_WORKING_MONMENT1.getName(),resultMaximumWorkingMoment1List);
        map.put(DeviceParamsEnum.MAXIMUM_WORKING_MONMENT2.getName(),resultMaximumWorkingMoment2List);
        return AjaxResult.success(map);
    }

    @Override
    public void getEnergyConsumptionRate(String deviceCodes) {
        if (deviceCodes != null) {
            String[] deviceCodeList = deviceCodes.split(",");
            //设备编号
            for (String deviceCode : deviceCodeList) {
                //获取设备运行状态
                DeviceLog runStatusLog = scadaData.getDeviceLog(DeviceParamsEnum.RUN_STATE.getName());
                //判断设备状态
                if (runStatusLog != null) {
                    //获取能耗
                    DeviceLog energyConsumptionDeviceLog = scadaData.getDeviceLog(DeviceParamsEnum.ENERGY_CONSUMPTION.getName());
                    if (energyConsumptionDeviceLog != null) {
                        //保存设备数据
                        energyConsumptionDeviceLog.setVal(new BigDecimal(energyConsumptionDeviceLog.getVal()).divide(new BigDecimal(100),2,BigDecimal.ROUND_HALF_UP).toString());
                        energyConsumptionDeviceLog.setDeviceStatus(runStatusLog.getVal());
                        deviceLogService.save(energyConsumptionDeviceLog);
                    }
                }

            }
        }
    }
}
